package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Resource
    private BrandService brandService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private SpuDetailService detailService;
    @Resource
    private SkuService skuService;


    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        int current = Math.max(page,1);
        int size = Math.min(rows,5);

        Page<Spu> result = query()
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", categoryId)
                .eq(id != null, "id", id)
                .page(new Page<>(current, size));

        List<SpuDTO> spuDTOs = SpuDTO.convertEntityList(result.getRecords());
        for (SpuDTO spuDTO : spuDTOs) {
            handleCategoryAndBrandName(spuDTO);
        }
        return new PageDTO<>(result.getTotal(),result.getPages(),spuDTOs);
    }

    public void handleCategoryAndBrandName(SpuDTO spuDTO) {
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if (brand!=null) {
            spuDTO.setBrandName(brand.getName());
        }

        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if (!CollectionUtils.isEmpty(categories)){
            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }

    }

    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean success = save(spu);
        if (!success){
            throw new LyException(500,"新增商品失败");
        }

        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        success = detailService.save(spuDetail);
        if (!success){
            throw new LyException(500,"新增商品详情失败");
        }

        for (SkuDTO skuDTO : spuDTO.getSkus()) {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spuDTO.getId());
            skuService.save(sku);
        }
    }

    @Autowired
    private AmqpTemplate amqpTemplate;
    @Transactional
    @Override
    public void updateSaleable(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean success = updateById(spu);
        if (!success){
            throw new LyException(500, "更新失败");
        }

        success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!success){
            throw new LyException(500, "更新失败");
        }

        String routingKey = saleable ? "up":"down";
        this.amqpTemplate.convertAndSend("jhj",routingKey,id);
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
        Spu spu = getById(id);
        if (spu == null){
            throw new LyException(400, "商品id不存在！");
        }

        SpuDTO spuDTO = new SpuDTO(spu);
        SpuDetail spuDetail = detailService.getById(id);
        if (spuDetail == null){
            throw new LyException(400, "商品id不存在！");
        }
        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));

        List<Sku> skus = skuService.query().eq("spu_id", id).list();
        if (CollectionUtils.isEmpty(skus)){
            throw new LyException(400, "商品id不存在！");
        }
        List<SkuDTO> skuDTOs = SkuDTO.convertEntityList(skus);
        spuDTO.setSkus(skuDTOs);
        handleCategoryAndBrandName(spuDTO);
        return spuDTO;
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        Long id = spuDTO.getId();
        if (id != null){
            Spu spu = spuDTO.toEntity(Spu.class);
            boolean success = updateById(spu);
            if (!success){
                throw  new LyException(500,"更新商品失败！");
            }
        }

        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        if (spuDetail != null && spuDetail.getSpuId()!= null){
            boolean success = detailService.updateById(spuDetail.toEntity(SpuDetail.class));
            if (!success){
                throw new LyException(500,"更新商品失败!");
            }
        }

        List<SkuDTO> skuDTOs = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(skuDTOs)){
            return;
        }
        Map<Boolean, List<Sku>> map = skuDTOs.stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
        List<Sku> insertOrUpdate = map.get(true);
        if (!CollectionUtils.isEmpty(insertOrUpdate)){
            skuService.saveOrUpdateBatch(insertOrUpdate);
        }

        List<Sku> delete = map.get(false);
        if (!CollectionUtils.isEmpty(delete)){
            List<Long> ids = delete.stream().map(Sku::getId).collect(Collectors.toList());
            skuService.removeByIds(ids);
        }
    }

}
